<!DOCTYPE html>
<html>
<head>
<title>Mass-Spring System</title>
<style>
  body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    background-color: #f0f0f0;
  }
  canvas {
    border: 1px solid #ccc;
    background-color: white;
  }
</style>
</head>
<body>
<canvas id="physicsCanvas" width="450" height="500"></canvas>
<script>
  const canvas = document.getElementById('physicsCanvas');
  const ctx = canvas.getContext('2d');

  // --- General Settings ---
  ctx.strokeStyle = 'black';
  ctx.lineWidth = 2;
  ctx.font = '20px Arial';
  ctx.fillStyle = 'black';
  ctx.lineCap = 'round';

  // --- Draw Support ---
  const supportY = 80;
  const supportStartX = 100;
  const supportEndX = 350;
  ctx.beginPath();
  ctx.moveTo(supportStartX, supportY);
  ctx.lineTo(supportEndX, supportY);
  ctx.stroke();

  // Draw hatching for the support
  const hatchLength = 15;
  const hatchSpacing = 20;
  ctx.lineWidth = 1.5;
  for (let x = supportStartX; x < supportEndX; x += hatchSpacing) {
    ctx.beginPath();
    ctx.moveTo(x, supportY);
    ctx.lineTo(x + hatchLength, supportY - hatchLength);
    ctx.stroke();
  }
  ctx.lineWidth = 2; // Reset line width

  // --- Draw Spring ---
  const centerX = (supportStartX + supportEndX) / 2;
  const springStartY = supportY;
  const springRadius = 22;
  const numCoils = 14;
  const coilSegmentHeight = 12; // vertical height of one semi-circle of the coil

  ctx.beginPath();
  // Top connector
  ctx.moveTo(centerX, springStartY);
  let currentY = springStartY + 5;
  ctx.lineTo(centerX, currentY);

  // Coils
  for (let i = 0; i < numCoils; i++) {
    // Right semi-circle
    ctx.arc(centerX, currentY + coilSegmentHeight / 2, springRadius, -Math.PI / 2, Math.PI / 2, false);
    currentY += coilSegmentHeight;
    // Left semi-circle
    ctx.arc(centerX, currentY - coilSegmentHeight / 2, springRadius, Math.PI / 2, -Math.PI / 2, false);
  }

  // Bottom connector
  const springEndY = currentY;
  ctx.lineTo(centerX, springEndY + 5);
  ctx.stroke();

  const objectTopY = springEndY + 5;

  // --- Draw Object ---
  const objWidth = 90;
  const objHeight = 50;
  const objX = centerX - objWidth / 2;
  const objY = objectTopY;

  ctx.fillStyle = '#BDBDBD'; // Grey color
  ctx.fillRect(objX, objY, objWidth, objHeight);
  ctx.strokeStyle = 'black';
  ctx.strokeRect(objX, objY, objWidth, objHeight);
  ctx.fillStyle = 'black'; // Reset fill style

  // --- Draw Labels ---

  // "spring" label
  ctx.textAlign = 'left';
  ctx.textBaseline = 'middle';
  ctx.fillText('spring', 40, 160);
  ctx.beginPath();
  ctx.moveTo(105, 160);
  ctx.lineTo(centerX - springRadius - 5, 160);
  ctx.stroke();

  // "object" label
  ctx.fillText('object', 40, objY + objHeight / 2);
  ctx.beginPath();
  ctx.moveTo(105, objY + objHeight / 2);
  ctx.lineTo(objX - 5, objY + objHeight / 2);
  ctx.stroke();

  // "oscillation" label
  const oscilX = objX + objWidth + 40;
  const oscilTopY = objY - 10;
  const oscilBottomY = objY + objHeight + 10;
  const oscilMidY = (oscilTopY + oscilBottomY) / 2;
  
  ctx.fillText('oscillation', oscilX + 15, oscilMidY);
  
  // Oscillation line
  ctx.beginPath();
  ctx.moveTo(oscilX, oscilTopY);
  ctx.lineTo(oscilX, oscilBottomY);
  ctx.stroke();

  // Arrowheads for oscillation line
  const arrowSize = 8;
  // Top arrow (pointing up)
  ctx.beginPath();
  ctx.moveTo(oscilX, oscilTopY);
  ctx.lineTo(oscilX - arrowSize / 1.5, oscilTopY + arrowSize);
  ctx.moveTo(oscilX, oscilTopY);
  ctx.lineTo(oscilX + arrowSize / 1.5, oscilTopY + arrowSize);
  ctx.stroke();
  // Bottom arrow (pointing down)
  ctx.beginPath();
  ctx.moveTo(oscilX, oscilBottomY);
  ctx.lineTo(oscilX - arrowSize / 1.5, oscilBottomY - arrowSize);
  ctx.moveTo(oscilX, oscilBottomY);
  ctx.lineTo(oscilX + arrowSize / 1.5, oscilBottomY - arrowSize);
  ctx.stroke();

  // --- Draw Caption ---
  ctx.font = 'bold 22px Arial';
  ctx.textAlign = 'center';
  ctx.textBaseline = 'bottom';
  ctx.fillText('Fig. 3.1', centerX, canvas.height - 20);

</script>
</body>
</html>